﻿using System;
using System.Collections.Generic;
using System.IO;
using ESRI.ArcGIS.ArcMapUI;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;

namespace ODM_Code.Code
{
    public class Clustering
    {
        private string outputFilePath;
        private List<ClusterItem> clusters;

        public Clustering(string outputFilePath)
        {
            this.outputFilePath = outputFilePath;
            clusters = new List<ClusterItem>();
        }

        public void CalculateAdjacent(IFeatureLayer treatFeat)
        {
            IPolygon pPolygon;
            ISelectionSet pSelSet;
            ISelectionSet pSelSet2;
            IEnumIDs pEnumIDs;
            IEnumIDs pEnumIDs2;
            int lID;
            int lID2;
            string sIDLst;

            IFeatureClass featClass = treatFeat.FeatureClass;

            // GET LIST OF FEATURES TO ITERATE OVER
            ISpatialFilter filter = new SpatialFilterClass();
            filter.SpatialRel = esriSpatialRelEnum.esriSpatialRelTouches;

            pSelSet = featClass.Select(filter, esriSelectionType.esriSelectionTypeIDSet, esriSelectionOption.esriSelectionOptionNormal, null);
            sIDLst = ";";
            pEnumIDs = pSelSet.IDs;
            pEnumIDs.Reset();
            lID = pEnumIDs.Next();

            
            while (lID >= 0)
            {
                if (lID != null) // =[FID]
                {
                    sIDLst = sIDLst + lID.ToString() + ";";
                }
                lID = pEnumIDs.Next();
            }

            pEnumIDs.Reset();
            lID = pEnumIDs.Next();

            while (lID >= 0)
            {
                if (lID != null) // =[FID]
                {
                    filter.Geometry = featClass.GetFeature(lID).Shape;
                    pSelSet2 = featClass.Select(filter, esriSelectionType.esriSelectionTypeIDSet, esriSelectionOption.esriSelectionOptionNormal, null);
                    
                    pEnumIDs2 = pSelSet2.IDs;
                    pEnumIDs2.Reset();
                    lID2 = pEnumIDs2.Next();

                    /*  Second order loop
                    while (lID2 >= 0)
                    {
                        if (lID2 != [FID])
                        {
                            sIDLst = sIDLst + lID2.ToString();
                            lID2 = pEnumIDs2.Next();
                        }
                    }
                    */
                }

                lID = pEnumIDs.Next();
            }

            // Remove leading and trailing semicolon
            if (sIDLst == ";")
            {
                sIDLst = "";
            }
            else
            {
                sIDLst = sIDLst.Substring(2, sIDLst.Length - 2);
            }
        }

        private void AddClusterInfo(IFeature currentfeature, int[] adjacent)
        {
            int featureId = currentfeature.Fields.FindField("CUT_UN_ID");
            int featureIdVal = (int)(currentfeature.get_Value(featureId));
            int acres = currentfeature.Fields.FindField("Acres");
            double acresVal = (double)(currentfeature.get_Value(acres));
            int xcoord = currentfeature.Fields.FindField("X_Coord");
            double xcoordVal = (double)(currentfeature.get_Value(xcoord));
            int ycoord = currentfeature.Fields.FindField("Y_Coord");
            double ycoordVal = (double)(currentfeature.get_Value(ycoord));

            ClusterItem cu = new ClusterItem(featureIdVal, acres, xcoord, ycoord, adjacent);
            clusters.Add(cu);
        }

        private void WriteClusterFile()
        {
            clusters.Sort();

            StreamWriter clusterwriter = new StreamWriter(outputFilePath);
            clusterwriter.WriteLine("CUT_UN_ID\t Acres\t X_Coord\t Y_Coord\t Nghbr_ID ");

            foreach (ClusterItem item in clusters)
            {
                item.WriteItem(ref clusterwriter);
            }

            clusterwriter.Close();
        }

        private class ClusterItem : IComparable<ClusterItem>
        {
            public int CUT_UN_ID;
            public double acres;
            public double xcoord;
            public double ycoord;
            public int[] adjacentpolygons;

            public ClusterItem(int CUT_UN_ID, double acres, double xcoord, double ycoord, int[] adjacentpolygons)
            {
                this.CUT_UN_ID = CUT_UN_ID;
                this.acres = acres;
                this.xcoord = xcoord;
                this.ycoord = ycoord;
                this.adjacentpolygons = adjacentpolygons;
            }

            public void WriteItem(ref StreamWriter sw)
            {
                sw.Write(CUT_UN_ID.ToString() + '\t');
                sw.Write(acres.ToString() + '\t');
                sw.Write(xcoord.ToString() + '\t');
                sw.Write(ycoord.ToString() + '\t');

                string longstr = "\t";
                for (int i = 0; i < adjacentpolygons.Length; i++)
                {
                    longstr += adjacentpolygons[i].ToString() + "-";
                }
                longstr = longstr.Substring(0, longstr.Length - 1);
                
                sw.Write(longstr);
                sw.Write("\n");
            }

            public int CompareTo(ClusterItem that)
            {
                if (this.CUT_UN_ID > that.CUT_UN_ID)
                {
                    return -1;
                }
                else if (this.CUT_UN_ID < that.CUT_UN_ID)
                {
                    return 1;
                }
                else
                {
                    return 0;
                }
            }
        }
    }
}
